import processing.core.*; 
import processing.xml.*; 

import netscape.javascript.*; 
import processing.core.*; 
import traer.physics.*; 

import java.applet.*; 
import java.awt.Dimension; 
import java.awt.Frame; 
import java.awt.event.MouseEvent; 
import java.awt.event.KeyEvent; 
import java.awt.event.FocusEvent; 
import java.awt.Image; 
import java.io.*; 
import java.net.*; 
import java.text.*; 
import java.util.*; 
import java.util.zip.*; 
import java.util.regex.*; 

public class exercise6 extends PApplet {





//Setup variables
int screenWidth = 600;
int screenHeight = 600;
float mass = 1.0f;
float g = 0.0f;
float drag = 0.5f;
float springStrength = 0.5f;
float springDamp = 0.5f;
float attracStrength = -300;
float attracMinDist = 0;

int framerate = 30;
int bgColor = 99;
int objDiameter = 20;

ParticleSystem physics;

Particle grabbed;
Particle me;

ArrayList friends = new ArrayList();
PFont font;

int numberOfParticles = 50;

float absPointX = 0;
float absPointY = 0;
float prevMouseX = 0;
float prevMouseY = 0;
float moveX = 0;
float moveY = 0;

public void setup() {
  physics = new ParticleSystem(g, drag);
  physics.setIntegrator(ParticleSystem.MODIFIED_EULER);
  
  this.size(screenWidth,screenHeight);
  this.smooth();
  this.strokeWeight(0);
  this.ellipseMode(CENTER);
  this.frameRate(framerate); //Default 60
  font = createFont("Verdana-Bold", 11);
  this.textFont(font);
  this.colorMode(HSB, 360, 100, 100);  
  
  initProgram();
 
}

public void initProgram(){
  me = physics.makeParticle(mass, width/2, height/2, 0);
  friends.add("me");
  me.makeFixed();
}

//void createParticlesTest(int maxNumberOfParticles) {
//  if(physics.numberOfParticles() < maxNumberOfParticles) {
//    addParticle();
//    friends.add("friend");
//  }
//}

public void draw() {

//  createParticlesTest(numberOfParticles);
  
  physics.tick();
  translate(moveX, moveY);  
  this.background(0,0,bgColor);
  
  drawObjects();

}

public void drawObjects() {

  //grabbed object process
  if(grabbed != null) {
    grabbed.position().set(mouseX + absPointX, mouseY + absPointY, 0);
  }

  //draw Springs
  for(int i = 0; i < physics.numberOfSprings(); i++) {
    Spring s = physics.getSpring(i);
    drawSpring(s);
  }

  //draw Particles
  int h = 229;
  int s = 0;
  int v = 90;

  int numberOfParticles = physics.numberOfParticles();
  objDiameter = getDiameter(numberOfParticles);

  for(int i = 0; i < numberOfParticles; i++) {
    Particle p = physics.getParticle(i);
    
    double d = getDistance(p, me);

    s = 95 - (int)d/2;
    v = 90;
      
    if(s < 0){ 
      s = 0;
      v = 100;
    }
    
    fill(h, s, v);

    drawParticle(p);

    if(friends.size() > i){
      fill(0,0,0);
      textAlign(CENTER);
      text((String)friends.get(i), p.position().x() - absPointX ,p.position().y() - absPointY + objDiameter,0);
    }
//    text("absPointX:" + absPointX, 10, 10, 0);
//    text("absPointY:" + absPointY, 10, 20, 0);

  }
}



//Drawing Particle
public void drawParticle(Particle p){
  drawParticle(p.position().x(), p.position().y());
}

public void drawParticle(float x, float y){

  ellipse(x - absPointX, y - absPointY, objDiameter, objDiameter);
}

//Drawing Spring
public void drawSpring(Spring s) {
  this.line(s.getOneEnd().position().x() - absPointX, s.getOneEnd().position().y() - absPointY, s.getTheOtherEnd().position().x() - absPointX, s.getTheOtherEnd().position().y()- absPointY);
}

public Particle addParticle() {
  return addParticle(random(10,300));
}

public Particle addParticle(float distance){
  return addParticle(width/2 + random(-20, 20), height/2 + random(-20, 20), distance);
}


public Particle addParticle(float x, float y, float distance) {
  Particle p = physics.makeParticle(mass, x, y, 0);
  physics.makeSpring(p, me, springStrength, springDamp, distance);

  //avoid conflict
  for(int i = 0; i < physics.numberOfParticles(); i++) {
    Particle q = physics.getParticle(i);

    //check if it's a self
    if(!p.equals(q) && !q.equals(me)) {
      //physics.makeSpring(p, q, 0.1f, 0.001f, width/2);
      physics.makeAttraction(p, q, attracStrength, attracMinDist);
    }
  }
  return p;
}


public void addFriend(String name, float distance){
  addParticle(distance);
  friends.add(name);
}

public void clearGraph(){
  physics.clear();
  friends.clear();
  initProgram();
}

public double getDistance(Particle p, Particle q){
  return sqrt(pow(p.position().x() - q.position().x(), 2) + pow(p.position().y() - q.position().y(),2));

}

public int getDiameter(int numberOfParticles){
  int diameter = 10;
  if( numberOfParticles < 100){
    diameter = 100 * (100/9) / ( numberOfParticles  + (100/9));
  }
  return diameter;
}

//Event Handlers
public void mousePressed() {
  for(int i = 0; i < physics.numberOfParticles(); i++) {
    Particle p = physics.getParticle(i);
    if(abs(mouseX - p.position().x() + absPointX) < objDiameter && abs(mouseY - p.position().y() + absPointY) < objDiameter) {
      this.grabbed = p;
    }
  }
  if(grabbed == null){
    prevMouseX = mouseX;
    prevMouseY = mouseY;
  }
}

public void mouseReleased() {
  super.mouseReleased();
  this.grabbed = null;
}

public void mouseDragged(){
  if(grabbed == null){

    moveX = mouseX - prevMouseX;
    moveY = mouseY - prevMouseY;
    prevMouseX = mouseX;
    prevMouseY = mouseY;
    absPointX = absPointX - moveX;
    absPointY = absPointY - moveY;
  }
}
  static public void main(String args[]) {
    PApplet.main(new String[] { "--present", "--bgcolor=#666666", "--stop-color=#cccccc", "exercise6" });
  }
}
